#include <stdlib.h>
#include <stdio.h>
#include "elf.h"
#include "load.h"


typedef struct verif_ {
    Elf32_Off offset;
    Elf32_Word size;
} verif;


int main(int argc, char* argv[]) {
    if(argc != 3){
        printf ("\n\nErreur d'utilisation du programme !\n\nSyntaxe : >./etape3 fich_source.o fich_dest.o\n\n");
        return 0;
    }

    if(!estELF(argv[1])){
        printf ("\n\nErreur d'utilisation du programme !\n\nSyntaxe : >./etape3 fich_source.o fich_dest.o\n\n");
        return 0;
    }

    FILE* f1 = fopen(argv[1],"r");
    FILE* f2 = fopen(argv[2],"w");

    if(f1==NULL || f2==NULL){
        printf ("\n\nErreur lors de l'ouverture d'un des fichiers.\n\n");
        return 0;
    }

    verif * tab = NULL;
    int nbSecRel = 0,i,j,taille=0,taille_b=0;

    Elf32_Ehdr header = load_header(f1);
    Elf32_Shdr* sheader = load_section_headers(f1);
    Elf32_Shdr* sheader_bis = load_section_headers(f1);

    for(i=0;i<header.e_shnum;i++){
        if(sheader[i].sh_type==9){
            taille_b+=40;
            tab = realloc(tab,(nbSecRel+1)*sizeof(verif));
            tab[nbSecRel].offset = sheader[i].sh_offset;
            tab[nbSecRel].size = sheader[i].sh_size;
            nbSecRel++;
        }
    }

    header.e_shnum-=nbSecRel;
    header.e_shstrndx-=nbSecRel;
    for(i=0;i<16;i++){
        fwrite(&header.e_ident[i],1,1,f2);
    }
    fwrite(&header.e_type,1,2,f2);
    fwrite(&header.e_machine,1,2,f2);
    fwrite(&header.e_version,1,4,f2);
    fwrite(&header.e_entry,1,4,f2);
    fwrite(&header.e_phoff,1,4,f2);
    fwrite(&header.e_shoff,1,4,f2);
    fwrite(&header.e_flags,1,4,f2);
    fwrite(&header.e_ehsize,1,2,f2);
    fwrite(&header.e_phentsize,1,2,f2);
    fwrite(&header.e_phnum,1,2,f2);
    fwrite(&header.e_shentsize,1,2,f2);
    fwrite(&header.e_shnum,1,2,f2);
    fwrite(&header.e_shstrndx,1,2,f2);

    fseek(f2,header.e_shoff,SEEK_SET);

    for(i=0;i<(header.e_shnum+nbSecRel);i++){
        if(sheader[i].sh_link!=0){
            sheader[i].sh_link-=nbSecRel;
        }
        if(sheader[i].sh_offset>header.e_shoff){
            taille=taille_b;
        }
        if(sheader[i].sh_type!=9){
            fwrite(&sheader[i].sh_name,1,4,f2);
            fwrite(&sheader[i].sh_type,1,4,f2);
            fwrite(&sheader[i].sh_flags,1,4,f2);
            fwrite(&sheader[i].sh_addr,1,4,f2);
            for(j=0;j<nbSecRel;j++){
                if(tab[j].offset<sheader[i].sh_offset){
                    taille+=tab[j].size;
                }
            }
            sheader[i].sh_offset-=taille;
            fwrite(&sheader[i].sh_offset,1,4,f2);
            fwrite(&sheader[i].sh_size,1,4,f2);
            fwrite(&sheader[i].sh_link,1,4,f2);
            fwrite(&sheader[i].sh_info,1,4,f2);
            fwrite(&sheader[i].sh_addralign,1,4,f2);
            fwrite(&sheader[i].sh_entsize,1,4,f2);
        }
    taille = 0;
    }    
    char c;
    for(i=1;i<(header.e_shnum+nbSecRel);i++){
        if(sheader[i].sh_type!=9){
            fseek(f1,sheader_bis[i].sh_offset,SEEK_SET);
            fseek(f2,sheader[i].sh_offset,SEEK_SET);
            for(j=0;j<sheader_bis[i].sh_size;j++){
                c = fgetc(f1);
                fwrite(&c,1,1,f2);
            }
        }
    }    


    return 0;
}
